﻿<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <style type="text/css">
        .title {
            font-size: large;
            font-weight: bold;
            color: red;
        }

        .blue {
            color: blueviolet;
        }
    </style>
</head>
<body>
    <p class="title">函数的执行环境</p>
    <p>每次调用某个函数(执行某个函数的时候),系统会为该函数创建一个封闭的局部的运行环境,就是函数的执行环境.</p>
    <p>函数总是在自己的执行环境中运行,如读写局部变量,函数参数,运行内部逻辑等.</p>
    <p>创建执行环境的过程包含了创建函数作用域,函数也是在自己的作用域下面执行的.</p>
    <p>从另一个角度来说,每个函数的执行环境都有一个作用域链,子函数的作用域链包含了他的父函数的作用域链</p>
    <p class="title">作用域、作用域链、调用对象</p>
    <p>函数作用域分为<span class="blue">语法作用域和动态作用域</span></p>
    <p>语法作用域是<span class="blue">函数定义时的作用域</span>,即静态作用域.</p>
    <p>当定义一个函数时,他的语法作用域就确定了.语法作用域在函数结构的嵌套关系下,函数的作用范围</p>
    <p class="blue">作用域链就是把这些具有嵌套层级关系的作用域串联起来</p>
    <p>动态作用域就是<span class="blue">函数调用执行时的作用域,即动态作用域.</span></p>
    <p>当一个函数被调用的时候,首先将函数内部的属性指向函数的作用域链,然后会创建一个调用对象,并用该调用对象记录函数的参数和函数的局部变量,将其置于作用域链的顶部</p>
    <p>函数的内部属性[[scope]]指向了该作用域链</p>
    <p>动态作用域就是通过该调用对象来创建的,此时的[[scope]]除了具有定义时的作用域链,还具有调用时创建的调用对象</p>
    <p>换句话说就是执行环境下的作用域等于该函数定义时的作用域链加上函数创建时的调用对象,从而形成了新的作用域链</p>
    <p>作用域,其实就是一个对象链,这些对象就是函数调用时创建的调用对象,以及他上面的一层层的调用对象直到最上层的全局对象</p>
    <p>比如A函数里面有B函数,B函数的作用域链就是:B函数的作用域-->A函数的作用域-->window作用域</p>
    <p>当B函数被调用时,会按照B函数的作用域-->A函数的作用域-->window作用域来查找,实际上是B的调用对象-->A的调用对象-->全局对象来查找</p>
    <p>也就是说函数调用时,<span class="blue">函数的作用域链实际上是调用对象链</span></p>

    <p class="title">闭包</p>
    <p>在动态执行环境中,数据实时地发生变化,为了保持这些非持久型变量的值,我们用闭包这种载体来存储这些动态数据.这就是闭包的作用.</p>
    <p>也就说遇到需要存储动态变化的数据或将被回收的数据时,我们可以通过外面再包裹一层函数形成闭包来解决.</p>
    <p>当然,闭包会导致很多外部函数的调用对象不能释放,滥用闭包会使得内存泄露,所以在频繁生成闭包的情景下我们要估计下他带来的副作用.</p>
</body>
</html>
